package club.banyuan.demo.sec.config;

import club.banyuan.demo.sec.common.ApiResponse;
import club.banyuan.demo.sec.config.security.JwtAccessDeniedHandler;
import club.banyuan.demo.sec.config.security.JwtAuthenticationEntryPoint;
import club.banyuan.demo.sec.config.security.JwtAuthenticationFilter;
import club.banyuan.demo.sec.service.CustomUserDetailsService;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 访问白名单
     */
    public final static String[] PERMIT_URLS = new String[]{
            "/api/hello",
            "/api/auth/**",

            // 所有静态资源文件
            "/static/**",
            "/**/*.jpg",
            "/**/*.png",
            "/**/*.gif",
            "/**/*.js",
            "/**/*.css",

            // for swagger ui
            "/swagger-ui.html",
            "/swagger-resources/**",
            "/v2/api-docs/**",
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                // 关闭 CSRF & CORS
                .cors().and().csrf().disable()

                // 添加 JWT 过滤器
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)

                // 授权和认证异常处理
                .exceptionHandling()
                .authenticationEntryPoint(new JwtAuthenticationEntryPoint())
                .accessDeniedHandler(new JwtAccessDeniedHandler())

                // 禁用 Session (使用 JWT)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                // 允许白名单直接请求，其他一律走权限验证
                .and()
                .authorizeRequests()
                .antMatchers(PERMIT_URLS).permitAll()
                .anyRequest().access("@permissionService.hasPermission(request, authentication)");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }
}
